home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / rpc / rpcInit.c < prev    next >
C/C++ Source or Header  |  1991-03-18  |  17KB  |  511 lines

  1. /*
  2.  * rpcInit.c --
  3.  *
  4.  *    Initialize the data structures needed by the RPC system.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/rpc/RCS/rpcInit.c,v 9.13 90/10/09 11:58:48 jhh Exp Locker: mgbaker $ SPRITE (Berkeley)";
  12. #endif /* not lint */
  13.  
  14. #include <sprite.h>
  15. #include <stdio.h>
  16. #include <rpc.h>
  17. #include <rpcInt.h>
  18. #include <rpcClient.h>
  19. #include <rpcServer.h>
  20. #include <rpcTrace.h>
  21. #include <vm.h>
  22. #include <timer.h>
  23. #include <net.h>
  24.  
  25. /*
  26.  * These are the rpc version numbers, both in native format and in
  27.  * byte-swapped format. 
  28.  */
  29.  
  30. int    rpc_NativeVersion = RPC_NATIVE_VERSION;
  31. int    rpc_SwappedVersion = RPC_SWAPPED_VERSION;
  32. int    rpc_NativeVersionNew = RPC_NATIVE_VERSION_NEW;
  33. int    rpc_SwappedVersionNew = RPC_SWAPPED_VERSION_NEW;
  34.  
  35. /*
  36.  * Constant parameters for the protocol.  The RpcConst structure keeps
  37.  * the complete set of constants.  Two sets of constants are defined,
  38.  * one that is appropriate for a local ethernet, one that has longer
  39.  * timeouts and is better for talking across gateways.
  40.  */
  41. RpcConst rpcEtherConst;
  42. RpcConst rpcInetConst;
  43.  
  44. void RpcBufferInit();
  45.  
  46.  
  47. /*
  48.  *----------------------------------------------------------------------
  49.  *
  50.  * Rpc_Init --
  51.  *
  52.  *      Allocate and set up the tables used by the RPC system.  This
  53.  *      should be called after virtual memory allocation can be done and
  54.  *      before any RPCs are attempted.  This allocates the Client Channel
  55.  *    data structures and some stuff for the Rpc Servers' state.  The
  56.  *    number of client channels is fixed by rpcNumChannels, but the
  57.  *    number of RPC server processes can grow via the Rpc_Deamon process.
  58.  *
  59.  * Results:
  60.  *    None.
  61.  *
  62.  * Side effects:
  63.  *    Allocate space for tables, and set the initial state for the
  64.  *    client channels and the servers.
  65.  *
  66.  *----------------------------------------------------------------------
  67.  */
  68. void
  69. Rpc_Init()
  70. {
  71.     int i;
  72.     register int frag;
  73.     extern void    RpcInitServerTraces();
  74.  
  75.     /*
  76.      * Initialize sets of time parameters.  These structures are used in
  77.      * the RpcDoCall code.  This is much too hard coded, and someone
  78.      * should figure out how to dynamically determine these parameters.
  79.      *
  80.      * Ethernet - retry after 0.1 seconds, .5 seconds if fragmenting.
  81.      *    Double this until the retry interval is 1 second.
  82.      *    Retry at most 8 times, for a total timeout period of
  83.      *        .1 + .2 + .4 + .8 + 1.0 + 1.0 + 1.0 + 1.0 = 5.5
  84.      *        .5 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 = 7.5 (frag)
  85.      *    If we are recieving acks, then back off and probe every 5 seconds.
  86.      *    If we get acked 10 times then give a warning.
  87.      */
  88.     rpcEtherConst.retryMsec = 100;
  89.     rpcEtherConst.retryWait = 100 * timer_IntOneMillisecond;
  90.     rpcEtherConst.fragRetryMsec = 500;
  91.     rpcEtherConst.fragRetryWait = 500 * timer_IntOneMillisecond;
  92.     rpcEtherConst.maxAckMsec = 5000;
  93.     rpcEtherConst.maxAckWait = 5000 * timer_IntOneMillisecond;
  94.     rpcEtherConst.maxTimeoutMsec = 1000;
  95.     rpcEtherConst.maxTimeoutWait = 1000 * timer_IntOneMillisecond;
  96.     rpcEtherConst.maxTries = 8;
  97.     rpcEtherConst.maxAcks = 10;
  98.     /*
  99.      * Internet (IP) - retry after 0.5 seconds, 1.0 if fragmenting.
  100.      *    Double this until the retry interval is 4 seconds.
  101.      *    Retry at most 8 times, for a total timeout period of
  102.      *        .5 + 1.0 + 2.0 + 4.0 + 4.0 + 4.0 + 4.0 + 4.0 = 23.5
  103.      *        1.0 + 2.0 + 4.0 + 4.0 + 4.0 + 4.0 + 4.0 + 4.0 = 27.0 (frag)
  104.      *    If we are recieving acks, then back off and probe every 5 seconds.
  105.      *    If we get acked 10 times then give a warning.
  106.      */
  107.     rpcInetConst.retryMsec = 500;
  108.     rpcInetConst.retryWait = 500 * timer_IntOneMillisecond;
  109.     rpcInetConst.fragRetryMsec = 1000;
  110.     rpcInetConst.fragRetryWait = 1000 * timer_IntOneMillisecond;
  111.     rpcInetConst.maxAckMsec = 5000;
  112.     rpcInetConst.maxAckWait = 5000 * timer_IntOneMillisecond;
  113.     rpcInetConst.maxTimeoutMsec = 4000;
  114.     rpcInetConst.maxTimeoutWait = 4000 * timer_IntOneMillisecond;
  115.     rpcInetConst.maxTries = 8;
  116.     rpcInetConst.maxAcks = 10;
  117.  
  118.     /*
  119.      * TRACE and HISTOGRAM initialization.
  120.      */
  121.     Trace_Init(rpcTraceHdrPtr, RPC_TRACE_LEN, sizeof(RpcHdr), 0);
  122.  
  123.     rpcServiceTime[0] = (Rpc_Histogram *)NIL;
  124.     rpcCallTime[0] = (Rpc_Histogram *)NIL;
  125.     for (i=1 ; i<=RPC_LAST_COMMAND ; i++) {
  126.     rpcServiceTime[i] = Rpc_HistInit(RPC_NUM_HIST_BUCKETS, 1024);
  127.     rpcCallTime[i] = Rpc_HistInit(RPC_NUM_HIST_BUCKETS, 1024);
  128.     }
  129.  
  130.     /*
  131.      * Set our preferred inter-fragment delay based on machine type.
  132.      * This is a microsecond value.  Our output rate starts the same
  133.      * as the input rate, although MyDelay could increase if a machine
  134.      * senses that it is overloaded.
  135.      */
  136.  
  137.     RpcGetMachineDelay(&rpcMyDelay, &rpcOutputRate);
  138.  
  139.     /*
  140.      * The client channel table is kept as a pointer to an array of pointers
  141.      * to client channels.  First allocate the table of pointers and then
  142.      * allocate storage for each channel.
  143.      */
  144.     rpcChannelPtrPtr = (RpcClientChannel **)
  145.         Vm_RawAlloc(rpcNumChannels * sizeof(RpcClientChannel *));
  146.  
  147.     /*
  148.      * Query the net module of the maximum size protocol header buffer 
  149.      * needed.
  150.      */
  151.     for (i=0 ; i<rpcNumChannels ; i++) {
  152.     register RpcClientChannel *chanPtr;
  153.  
  154.     chanPtr = (RpcClientChannel *)Vm_RawAlloc(sizeof(RpcClientChannel));
  155.     rpcChannelPtrPtr[i] = chanPtr;
  156.  
  157.     chanPtr->state = CHAN_FREE;
  158.     chanPtr->index = i;
  159.     chanPtr->serverID = -1;
  160.     Sync_SemInitDynamic(&chanPtr->mutex,"Rpc:RpcClientChannel.mutex");
  161.     Sync_SemRegister(&chanPtr->mutex);
  162.     chanPtr->waitCondition.waiting = FALSE;
  163.  
  164.     /*
  165.      * Set up header storage and the scatter/gather sets used to
  166.      * refer to a whole message.  This is done for each type
  167.      * of packet (request, reply ack), plus an array of these
  168.      * things used for fragmenting our request.
  169.      */
  170.     RpcBufferInit((RpcHdr *) &chanPtr->requestRpcHdr, &chanPtr->request,
  171.             chanPtr->index, -1);
  172.     RpcBufferInit(&chanPtr->replyRpcHdr, &chanPtr->reply,
  173.             chanPtr->index, -1);
  174.     RpcBufferInit(&chanPtr->ackHdr, &chanPtr->ack,
  175.             chanPtr->index, -1);
  176.  
  177.     for (frag=0 ; frag < RPC_MAX_NUM_FRAGS ; frag++) {
  178.         RpcBufferInit(&chanPtr->fragRpcHdr[frag], &chanPtr->fragment[frag],
  179.                 chanPtr->index, -1);
  180.     }
  181.  
  182.     }
  183.     /*
  184.      * Initialize server nack info.
  185.      */
  186.     Sync_SemInitDynamic(&rpcNack.mutex,"Rpc:RpcNackData.mutex");
  187.     Sync_SemRegister(&rpcNack.mutex);
  188.     /*
  189.      * Set nack buffers to NIL until allocated when rpc system turned on.
  190.      */
  191.     rpcNack.numFree = 0;
  192.     rpcNack.rpcHdrArray = (RpcHdr *) NIL;
  193.     rpcNack.hdrState = (int *) NIL;
  194.     rpcNack.bufferSet = (RpcBufferSet *) NIL;
  195.  
  196.     /*
  197.      * Initialize client's table on whether servers are sending negative
  198.      * acknowledgements or not (if channel ramping-down is used).
  199.      */
  200.     RpcInitServerChannelState();
  201.  
  202.     /*
  203.      * Initialize neg-ack back-off constants on clients.
  204.      */
  205.     rpcNackRetryWait = 2 * timer_IntOneSecond;
  206.     rpcMaxNackWait = 15 * timer_IntOneSecond;
  207.  
  208.     /*
  209.      * Initialize the servers' state table.  Most slots are left
  210.      * uninitialized.  They get filled in by Rpc_Deamon when it creates
  211.      * new server processes.  After creation, a server process
  212.      * claims a table entry with RpcServerInstall.
  213.      */
  214.     rpcServerPtrPtr = (RpcServerState **)
  215.         Vm_RawAlloc(rpcAbsoluteMaxServers * sizeof(RpcServerState *));
  216.     for (i=0 ; i<rpcMaxServers ; i++) {
  217.     rpcServerPtrPtr[i] = (RpcServerState *)NIL;
  218.     }
  219.  
  220.     /*
  221.      * Ask the net module to set up our Sprite ID.  It uses either
  222.      * existing (compiled in) addresses or Reverse ARP.  If we can't
  223.      * figure out our ID we use zero and rely on the RPC server to
  224.      * propogate our Sprite ID back in the first RPC reply message.
  225.      * We try all the interfaces until we get one that works.
  226.      */
  227.     for (i = 0; ; i++) {
  228.     Net_Interface    *interPtr;
  229.     interPtr = Net_NextInterface(TRUE, &i);
  230.     if (interPtr == (Net_Interface *) NIL) {
  231.         break;
  232.     }
  233.     rpc_SpriteID = Net_AddrToID(interPtr->netType, NET_PROTO_RAW,
  234.                 &interPtr->netAddress[NET_PROTO_RAW]);
  235.     if (rpc_SpriteID > 0) {
  236.         break;
  237.     }
  238.     }
  239.     if (rpc_SpriteID < 0) {
  240.     rpc_SpriteID = 0;
  241.     }
  242.  
  243.     RpcInitServerTraces();
  244.  
  245.     return;
  246. }
  247.  
  248. /*
  249.  *----------------------------------------------------------------------
  250.  *
  251.  * RpcBufferInit --
  252.  *
  253.  *    Initialize a packet buffer for one of the various packets sent
  254.  *    via an RPC channel.  They all share the same packet format and
  255.  *    buffering system, and this call is used to initialize it.
  256.  *
  257.  * Results:
  258.  *    None.
  259.  *
  260.  * Side effects:
  261.  *    Allocate memory with Vm_RawAlloc.  Give initial values to
  262.  *    the fields of the RPC header that never change.  These are:
  263.  *    version        # byte ordering version.
  264.  *    channel        # channel port number.
  265.  *    delay        # interfragment delay.
  266.  *    paramSize 0    # size of the parameter area of the message.
  267.  *    dataSize 0    # size of the data area of the message.
  268.  *    numFrags 0    # >0 if fragmented
  269.  *    fragMask 0    # fragmentID
  270.  *
  271.  *----------------------------------------------------------------------
  272.  */
  273. void
  274. RpcBufferInit(rpcHdrPtr, bufferSetPtr, channel, serverHint)
  275.     RpcHdr *rpcHdrPtr;        /* Storage for packet header */
  276.     RpcBufferSet *bufferSetPtr;    /* Scatter/gather vector for whole message */
  277.     int channel;        /* chanPtr->index */
  278.     int serverHint;        /* srvPtr->index */
  279. {
  280.     int maxHdrSize = NET_MAX_HEADER_SIZE;
  281.  
  282.     bufferSetPtr->protoHdrBuffer.length = maxHdrSize;
  283.     bufferSetPtr->protoHdrBuffer.bufAddr = Vm_RawAlloc(maxHdrSize);
  284.     bufferSetPtr->protoHdrBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  285.  
  286.     bufferSetPtr->rpcHdrBuffer.length = sizeof(RpcHdr);
  287.     bufferSetPtr->rpcHdrBuffer.bufAddr = (Address)rpcHdrPtr;
  288.     bufferSetPtr->rpcHdrBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  289.  
  290.     bufferSetPtr->paramBuffer.length = 0;
  291.     bufferSetPtr->paramBuffer.bufAddr = (Address)NIL;
  292.     bufferSetPtr->paramBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  293.  
  294.     bufferSetPtr->dataBuffer.length = 0;
  295.     bufferSetPtr->dataBuffer.bufAddr = (Address)NIL;
  296.     bufferSetPtr->dataBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  297.     /*
  298.      * Set up RPC header fields that don't change.
  299.      */
  300.     rpcHdrPtr->version = rpc_NativeVersion;
  301.     rpcHdrPtr->delay = rpcMyDelay;
  302.  
  303.     rpcHdrPtr->clientID = rpc_SpriteID;
  304.     rpcHdrPtr->channel = channel;
  305.     rpcHdrPtr->serverID = rpc_SpriteID;
  306.     rpcHdrPtr->serverHint = serverHint;
  307.     /*
  308.      * And some that might not have to change.
  309.      */
  310.     rpcHdrPtr->numFrags = 0;
  311.     rpcHdrPtr->fragMask = 0;
  312.     rpcHdrPtr->paramSize = 0;
  313.     rpcHdrPtr->dataSize = 0;
  314. }
  315.  
  316. /*
  317.  *----------------------------------------------------------------------
  318.  *
  319.  * RpcInitServerState --
  320.  *
  321.  *    Initialize a server state table entry.  This is called before
  322.  *    a server process is created to set up its state.  The state is
  323.  *    used as the primary communication mechanism between the server
  324.  *    process and the rest of the world.
  325.  *
  326.  * Results:
  327.  *    A pointer to an initialized server state table entry.  This
  328.  *    value needs to be saved in a table somewhere by the caller.
  329.  *
  330.  * Side effects:
  331.  *    Allocate memory with Vm_RawAlloc.  Give initial values to
  332.  *    all the elements of the table entry.  The "state" field of
  333.  *    the table is set to SRV_NOTREADY and a server process has
  334.  *    to claim the table entry with RpcServerInstall.
  335.  *
  336.  *----------------------------------------------------------------------
  337.  */
  338. RpcServerState *
  339. RpcInitServerState(index)
  340.     int index;        /* Caller's index of returned info.  This is saved
  341.              * in the table and used as a hint to clients */
  342. {
  343.     register RpcServerState *srvPtr;    /* Server state that is initialized */
  344.     register int frag;            /* Index into array of headers used
  345.                      * for fragmenting */
  346.     static Sync_Semaphore mutexInit =
  347.     Sync_SemInitStatic("RpcServerState->mutex");
  348.  
  349.     Sync_SemRegister(&mutexInit);
  350.  
  351.     srvPtr = (RpcServerState *)Vm_RawAlloc(sizeof(RpcServerState));
  352.  
  353.     srvPtr->state = SRV_NOTREADY;
  354.     srvPtr->ID = 0;
  355.     srvPtr->freeReplyProc = (int (*)())NIL;
  356.     srvPtr->freeReplyData = (ClientData)NIL;
  357.     srvPtr->index = index;
  358.     srvPtr->clientID = -1;
  359.     srvPtr->channel = -1;
  360.     srvPtr->mutex = mutexInit;
  361.     srvPtr->waitCondition.waiting = FALSE;
  362.  
  363.     /*
  364.      * Set up the buffer address for the RPC header of replies
  365.      * and acks to point to the headers kept here in the server's state.
  366.      */
  367.     RpcBufferInit(&srvPtr->replyRpcHdr, &srvPtr->reply, -1, srvPtr->index);
  368.     RpcBufferInit(&srvPtr->ackRpcHdr, &srvPtr->ack, -1, srvPtr->index);
  369.     for (frag=0 ; frag < RPC_MAX_NUM_FRAGS ; frag++) {
  370.     RpcBufferInit(&srvPtr->fragRpcHdr[frag], &srvPtr->fragment[frag],
  371.             -1, srvPtr->index);
  372.     }
  373.     /*
  374.      * Set up the scatter vector for input requests to the server.
  375.      * Allocate buffer space for the largest possible request.
  376.      */
  377.     RpcBufferInit(&srvPtr->requestRpcHdr, &srvPtr->request, -1, srvPtr->index);
  378.     srvPtr->request.paramBuffer.bufAddr = Vm_RawAlloc(RPC_MAX_PARAMSIZE);
  379.     srvPtr->request.paramBuffer.length = RPC_MAX_PARAMSIZE;
  380.  
  381.     srvPtr->request.dataBuffer.bufAddr = Vm_RawAlloc(RPC_MAX_DATASIZE);
  382.     srvPtr->request.dataBuffer.length = RPC_MAX_DATASIZE;
  383.  
  384.     /*
  385.      * Initialize temporaries.
  386.      */
  387.     srvPtr->actualParamSize = 0;
  388.     srvPtr->actualDataSize = 0;
  389.  
  390.     return(srvPtr);
  391. }
  392.  
  393. /*
  394.  *----------------------------------------------------------------------
  395.  *
  396.  * Rpc_Start --
  397.  *
  398.  *      Conduct the preliminary RPC's neccesary to start up the client
  399.  *      side of the RPC system.  A Get Time RPC is done to initialize the
  400.  *      boot time stamp.
  401.  *
  402.  * Results:
  403.  *    None.
  404.  *
  405.  * Side effects:
  406.  *    Do a Get Time RPC to initialize rpcBootID;
  407.  *
  408.  *----------------------------------------------------------------------
  409.  */
  410. void
  411. Rpc_Start()
  412. {
  413.     Time     bootTime;    /* Time returned from the default server */
  414.     int     tzMinutes;    /* Minutes west of Greenwich */
  415.     int     tzDST;        /* Daylight savings flag */
  416.     ReturnStatus status;    /* Status code from the RPC */
  417.     char     dateString[40];/* To hold a printable version of the time */
  418.     int     seconds;
  419.     int     spriteID;
  420.     Net_Route        *routePtr;
  421.     Sync_Semaphore    tmpMutex;
  422.     int            i;
  423.  
  424.     /*
  425.      * Do a Sprite reverse Arp to discover our Sprite ID.  If it's still
  426.      * zero after this that inhibits the RPC system.  In that case we'd
  427.      * better be a diskfull machine so we find out our SpriteID by
  428.      * the user program that installs routes.  See Net_InstallRoute.
  429.      *
  430.      * We do a reverse arp on all the broadcast routes until one
  431.      * works.
  432.      */
  433.     spriteID = -1;
  434.     i = 0;
  435.     Sync_SemInitDynamic(&tmpMutex, "Rpc_Start:tmpMutex");
  436.     while (1) {
  437.     routePtr = Net_IDToRoute(NET_BROADCAST_HOSTID, i, FALSE, 
  438.             (Sync_Semaphore *) NIL, 0);
  439.     if (routePtr == (Net_Route *) NIL) {
  440.         break;
  441.     }
  442.     MASTER_LOCK(&tmpMutex);
  443.     spriteID = Net_RevArp(routePtr, NET_PROTO_RAW,  
  444.             (Net_Address *) NIL, &tmpMutex); 
  445.     MASTER_UNLOCK(&tmpMutex);
  446.     Net_ReleaseRoute(routePtr);
  447.     if (spriteID > 0) {
  448.         rpc_SpriteID = spriteID;
  449.         printf("Reverse Arp, setting Sprite ID to %d\n", spriteID);
  450.         break;
  451.     }
  452.     i++;
  453.     }
  454.  
  455.     Rpc_StampTest();
  456.  
  457.     status = Rpc_GetTime(RPC_BROADCAST_SERVER_ID, &bootTime, &tzMinutes,
  458.                          &tzDST);
  459.     if (status != SUCCESS) {
  460.     Timer_Ticks ticks;
  461.  
  462.     printf("Rpc_Start: error (%x) from Get Time RPC\n", status);
  463.     Timer_GetCurrentTicks(&ticks);
  464.     Timer_TicksToTime(ticks, &bootTime);
  465.     } else {
  466.     Timer_SetTimeOfDay(bootTime, tzMinutes, tzDST);
  467.     }
  468.     rpcBootID = bootTime.seconds;
  469.  
  470.     /*
  471.      * Convert from Greenwich Standard minutes to local minutes
  472.      * and print the time on the console.
  473.      */
  474.     seconds = bootTime.seconds + tzMinutes * 60;
  475.     Time_ToAscii(seconds, FALSE, dateString);
  476.     printf("%s\n", dateString);
  477. }
  478.  
  479. /*
  480.  *----------------------------------------------------------------------
  481.  *
  482.  * Rpc_MaxSizes --
  483.  *
  484.  *      This function returns the maximum amount of data that can be sent
  485.  *      in one RPC.  A remote procedure has its inputs and outputs packed
  486.  *      into two buffers called the "data area" and the "parameter area".
  487.  *      Two values are returned, the maximums for the parameter and data
  488.  *      areas.
  489.  *
  490.  * Results:
  491.  *    The first parameter gets the maximum data size, the
  492.  *    second gets the maximum parameter size.
  493.  *
  494.  * Side effects:
  495.  *    None.
  496.  *
  497.  *----------------------------------------------------------------------
  498.  */
  499. void
  500. Rpc_MaxSizes(maxDataSizePtr, maxParamSizePtr)
  501.     int *maxDataSizePtr;
  502.     int *maxParamSizePtr;
  503. {
  504.     if (maxDataSizePtr != (int *)NIL){
  505.     *maxDataSizePtr = RPC_MAX_DATASIZE;
  506.     }
  507.     if (maxParamSizePtr != (int *)NIL){
  508.     *maxParamSizePtr = RPC_MAX_PARAMSIZE;
  509.     }
  510. }
  511.